package com.springboot.nacos.config.client;

import small.common.core.constants.CommonConstants;
import small.common.core.util.StringUtil;
import com.small.nacos.api.config.ConfigService;
import com.springboot.nacos.config.NacosConfigManager;
import com.springboot.nacos.config.NacosConfigProperties;
import com.springboot.nacos.config.NacosPropertySourceRepository;
import com.springboot.nacos.config.refresh.NacosContextRefresher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;

/**
 * 拓展配置文件
 * Application容器刷新前（prepareContext阶段) 将nacos配置转换为PropertySource注入了Environment。
 */
public class NacosPropertySourceLocator implements PropertySourceLocator {

    protected static final Logger LOGGER = LoggerFactory.getLogger(NacosPropertySourceLocator.class);

    private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";

    private NacosConfigProperties nacosConfigProperties;

    private NacosConfigManager nacosConfigManager;

    private NacosPropertySourceBuilder nacosPropertySourceBuilder;

    public NacosPropertySourceLocator(NacosConfigManager nacosConfigManager) {
        this.nacosConfigManager = nacosConfigManager;
        this.nacosConfigProperties = nacosConfigManager.getNacosConfigProperties();
    }

    @Override
    public PropertySource<?> locate(Environment env) {
        //1.初始化配置服务
        ConfigService configService = nacosConfigManager.getConfigService();
        if (null == configService) {
            LOGGER.warn("no instance of config service found, can't load config from nacos");
            return null;
        }
        int timeout = nacosConfigProperties.getTimeout();
        nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService, timeout);


        String dataIdPrefix = nacosConfigProperties.getName();
        if (StringUtil.isBlank(dataIdPrefix)) {
            dataIdPrefix = env.getProperty("spring.application.name");
        }
        CompositePropertySource composite = new CompositePropertySource(NACOS_PROPERTY_SOURCE_NAME);
        //2.加载配置
        loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties);

        return composite;
    }

    private void loadApplicationConfiguration(CompositePropertySource compositePropertySource, String dataIdPrefix,
            NacosConfigProperties properties) {

        String fileExtension = properties.getFileExtension();
        String nacosGroup = properties.getGroup();
        loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup, fileExtension, true);
        loadNacosDataIfPresent(compositePropertySource, dataIdPrefix + CommonConstants.DOT + fileExtension, nacosGroup, fileExtension, true);
    }

    private void loadNacosDataIfPresent(final CompositePropertySource composite,
                                        final String dataId, final String group, String fileExtension,
                                        boolean isRefreshable) {
        if (null == dataId || dataId.trim().length() < 1) {
            return;
        }
        if (null == group || group.trim().length() < 1) {
            return;
        }
        NacosPropertySource nacosPropertySource = this.loadNacosPropertySource(dataId, group,
                fileExtension, isRefreshable);
        composite.addFirstPropertySource(nacosPropertySource);
    }

    private NacosPropertySource loadNacosPropertySource(final String dataId, final String group, String fileExtension, boolean isRefreshable) {

        if (NacosContextRefresher.getRefreshCount() != 0) {
            if (!isRefreshable) {
                return NacosPropertySourceRepository.getNacosPropertySource(dataId,
                        group);
            }
        }
        return nacosPropertySourceBuilder.build(dataId, group, fileExtension, isRefreshable);
    }
}
